package com.huang.auth.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;

/**
 * @author HuangShen
 * @Description 密码加密
 * @create 2021-09-25 8:54
 */
@Slf4j
public class MyPasswordEncoder {


    /**
     * 密码加密
     *
     * @param rawPassword 密码明文
     * @return string 加密密码
     */
    public static String encode(String rawPassword) {
        StringBuilder encodePassword = new StringBuilder();
        // 生成盐
        String salt = getSalt(10);
        // 对盐进行hash加密
        String saltH = getHash(salt);
        //hash 后的盐与 密码明文进行加密
        String pawH = getHash(saltH + rawPassword);
        encodePassword.append(saltH);
        encodePassword.append(".");
        encodePassword.append(pawH);
        return encodePassword.toString();
    }


    /**
     * 密码匹配
     *
     * @param rawPassword    密码明文
     * @param encodePassword 密码密文
     * @return boolean 比对结果
     */
    public static boolean matches(String rawPassword, String encodePassword) {

        String[] split = encodePassword.split("\\.");
        // 对明文进行加密
        String rawPasswordH = getHash(split[0] + rawPassword);
        return StringUtils.equals(split[0], rawPassword);


    }


    /**
     * 随机盐生成
     *
     * @param n 盐的长度
     * @return 生成的盐
     */
    private static String getSalt(int n) {
        char[] chars = "bakfbaowbfjkpbofbfaCCUVUIsIWDKV%$&^%*&*%$11314927315".toCharArray(); //转换为字符数组
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < n; i++) {
            char ch = chars[new Random().nextInt(chars.length)];
            stringBuilder.append(ch);
        }
        return stringBuilder.toString();
    }


    public static String getHash(String source) {
        // 用来将字节转换成 16 进制表示的字符
        char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

        try {
            MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
            sha256.update(source.getBytes()); // 通过使用 update 方法处理数据,使指定的 byte数组更新摘要
            byte[] encryptStr = sha256.digest(); // 获得密文完成哈希计算,产生128 位的长整数
            char[] str = new char[16 * 2]; // 每个字节用 16 进制表示的话，使用两个字符
            int k = 0; // 表示转换结果中对应的字符位置
            for (int i = 0; i < 16; i++) { // 从第一个字节开始，对每一个字节,转换成 16 进制字符的转换
                byte byte0 = encryptStr[i]; // 取第 i 个字节
                str[k++] = hexDigits[byte0 >>> 4 & 0xf]; // 取字节中高 4 位的数字转换, >>> 为逻辑右移，将符号位一起右移
                str[k++] = hexDigits[byte0 & 0xf]; // 取字节中低 4 位的数字转换
            }
            return new String(str); // 换后的结果转换为字符串
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

}
